Собств.отд
Главная     ◄Глагол     ◄Азбука     ◄Задачи на Глаголе     Примеры приложений ►   Среда разработки ►   Отладка программ ►   Отличия от Оберона ►   Отличия от Паскаля ►   Ассемблер ARM ►   Глагол для ARM ►   ? и Ответы
 
 glagol.png Программируем по-русски
 

Основная задача Глагола — дать человеку возможность воплощать свои мысли на языке, близком к его родному языку.

Издатель Глагола
 

 

(******************************************************************************)
(**)                        ОТДЕЛ Собств;
(******************************************************************************
 * НАЗНАЧЕНИЕ: вычисление собственных (с.) значений и векторов
 *
 * Источники, ссылки, библиография
   Debord J., Библиотека математических подпрограмм
   tpmath.zip

   Goffe B., Программа SimAnn.FOR (Simulated Annealing in Fortran)
   http://www.netlib.org/opt/simann.f

   EISPACK: Библиотека Фортран функций для вычисления собственных значений и векторов
   http://www.netlib.org/eispack

   Marsaglia G., Тесты для генераторов случайных чисел
   http://stat.fsu.edu/~geo/diehard.html

   Moshier S., Библиотека математических подпрограмм
   http://www.moshier.net

   Press W.H., Teukolsky S.A., Vetterling W.T., Flannery B.P.
   Численные рецепты на Паскале
   http://garbo.uwasa.fi/pc/turbopas.html

   Пакет численных методов для Турбо Паскаля
   Borland International, 1986
 *
 ******************************************************************************)
ИСПОЛЬЗУЕТ Матем,Вект,Матр;

ВИД 
  Вещ = Матем.Вещ;            
                                                    (* заготовки ЗАДАЧ *)
(******************************************************************************)
ЗАДАЧА^ Якоби-(A+:Матр.Вид; проходов:ЦЕЛ; точность:Вещ; СВ+:Матр.Вид; сз+:Вект.Вид):ЦЕЛ;
(* Цель:  вычисление с. значений и с. векторов методом Якоби
 ******************************************************************************
 * До:    < A >      - исходная матрица
 *        <проходов> - максимальное число проходов
 *        <точность> - требуемая точность
 * После: < СВ > - матрица нормированных с. векторов (по строкам), 
 *               у которых первый элемент > 0
 *        < сз > - с. значения
 *        < A >  - разрушенная исходная матрица
 * Ответ: 0 или НЕТ_СХОДИМОСТИ *)

(******************************************************************************)
ЗАДАЧА^ Значения-(A+:Матр.Вид; сзВещ+,сзМнм+:Вект.Вид):ЦЕЛ;
(* Цель:  вычисление с. значений квадратной матрицы
 ******************************************************************************
 * До:    < A >   - исходная матрица
 * После: <сзВещ> - вещественная часть с. значений
 *        <сзМнм> - мнимая часть с. значений
 *        < A >   - разрушенная исходная матрица
 * Ответ: 0 или НЕТ_СХОДИМОСТИ *)

(******************************************************************************)
ЗАДАЧА^ Вектор-(A-:Матр.Вид; сз,точность:Вещ; св+:Вект.Вид):ЦЕЛ;
(* Цель:  вычисление одного с. вектора для соответствующего
 *        вещественного (кратного) с. значения
 ******************************************************************************
 * До:    < A >      - исходная матрица
 *        < сз >     - с. значение
 *        <точность> - требуемая точность
 * После: < св > - нормированный с. вектор, 
 *               у которого первый элемент > 0
 * Ответ: 0 или НЕТ_СХОДИМОСТИ *)

(******************************************************************************)
ЗАДАЧА^ КорниПолинома-(Coef-:Вект.Вид; Deg:ЦЕЛ; X_Re+,X_Im+:Вект.Вид):ЦЕЛ;
(* Цель:  вычисление действительных и комплексных корней действительного
 *        полинома методом companion матрицы
 ******************************************************************************
 * До:    < Coef > - коэффициенты полинома
 *        < Deg >  - степень полинома
 * После: < X_Re > - действительные части корней (в порядке возрастания)
 *        < X_Im > - мнимые части корней
 * Ответ: 0 или НЕТ_СХОДИМОСТИ *)

(******************************************************************************)
ЗАДАЧА Якоби-(A+:Матр.Вид; проходов:ЦЕЛ; точность:Вещ; СВ+:Матр.Вид; сз+:Вект.Вид):ЦЕЛ;
(* Цель:  вычисление с. значений и с. векторов методом Якоби
 ******************************************************************************
 * До:    < A >      - исходная матрица
 *        <проходов> - наибольшее число проходов
 *        <точность> - требуемая точность
 * После: < СВ > - матрица нормированных с. векторов (по строкам), 
 *               у которых первый элемент > 0
 *        < сз > - с. значения
 *        < A >  - разрушенная исходная матрица
 * Ответ: 0 или НЕТ_СХОДИМОСТИ *)
ПЕР
  sin,cos,tg,tg2тета:Вещ;
  квCos,квSin,sincos,сумКвДиаг:Вещ;
  Aii,Ajj,Aij,Aik,Ajk,СВik,СВjk,d:Вещ;
  i,j,k,проход,посл:ЦЕЛ;
  готово:КЛЮЧ;
УКАЗ
  посл:=РАЗМЕР(A)-1;
  проход:=0;
  ОТ i:=0 ДО посл ВЫП
    ОТ j:=0 ДО посл ВЫП
      ЕСЛИ  i = j ТО
        СВ[i,j]:=1
      ИНАЧЕ
        СВ[i,j]:=0 
      КОН 
    КОН 
  КОН;

  ПОВТОРЯТЬ
    готово:=ВКЛ;
    УВЕЛИЧИТЬ(проход);
    сумКвДиаг:=0;
    ОТ i:=0 ДО посл ВЫП
      сумКвДиаг:=сумКвДиаг+Матем.кв(A[i,i])
    КОН;

    ОТ i:=0 ДО посл-1 ВЫП
      ОТ j:=i+1 ДО посл ВЫП
        ЕСЛИ  МОДУЛЬ(A[i,j]) > точность*сумКвДиаг ТО
          готово:=ОТКЛ;
          (* вычисляем поворот *)
          d:=A[i,i]-A[j,j];
          ЕСЛИ  МОДУЛЬ(d) > Матем.МАШЕПС ТО
            tg2тета:=d/(2*A[i,j]);
            tg:=Матем.знак(tg2тета)*Матем.квкор(1+Матем.кв(tg2тета))-tg2тета;
            cos:=1/Матем.квкор(1+Матем.кв(tg));
            sin:=tg*cos
          ИНАЧЕ
            cos:=Матем.КВКОР2Д2;     (* квкор(2)/2 *)
            sin:=Матем.знак(A[i,j])*Матем.КВКОР2Д2
          КОН;
          (* поворачиваем матрицу *)
          квCos:=Матем.кв(cos);
          квSin:=Матем.кв(sin);
          sincos:=sin*cos;
          Aii:=A[i,i]*квCos+2*A[i,j]*sincos+A[j,j]*квSin;
          Ajj:=A[i,i]*квSin-2*A[i,j]*sincos+A[j,j]*квCos;
          Aij:=(A[j,j]-A[i,i])*sincos+A[i,j]*(квCos-квSin);
          ОТ k:=0 ДО посл ВЫП
            ЕСЛИ  (k # i) И (k # j) ТО
              Aik:= A[i,k]*cos+A[j,k]*sin;
              Ajk:=-A[i,k]*sin+A[j,k]*cos;
              A[i,k]:=Aik;
              A[k,i]:=Aik;
              A[j,k]:=Ajk;
              A[k,j]:=Ajk
            КОН 
          КОН;
          A[i,i]:=Aii;
          A[j,j]:=Ajj;
          A[i,j]:=Aij;
          A[j,i]:=Aij;

          (* поворачиваем с. вектора *)
          ОТ k:=0 ДО посл ВЫП
            СВik:= cos*СВ[i,k]+sin*СВ[j,k];
            СВjk:=-sin*СВ[i,k]+cos*СВ[j,k];
            СВ[i,k]:=СВik;
            СВ[j,k]:=СВjk
          КОН
        КОН
      КОН
    КОН
  ДО готово ИЛИ (проход > проходов);

  (* на диагонали преобразованной матрицы находятся с. значения *)
  ОТ i:=0 ДО посл ВЫП
    сз[i]:=A[i,i]
  КОН;

  ЕСЛИ  проход > проходов ТО
    ВОЗВРАТ Матр.НЕТ_СХОДИМОСТИ
  КОН;

  (* упорядочивание с. значений и с. векторов *)
  ОТ i:=0 ДО посл-1 ВЫП
    k:=i;
    d:=сз[i];
    ОТ j:=i+1 ДО посл ВЫП
      ЕСЛИ  сз[j] > d ТО
        k:=j;
        d:=сз[j]
      КОН 
    КОН;
    Матем.обмен(сз[i],сз[k]);
    Матр.ОбменСтрок(СВ,i,k)
  КОН;

  (* первый элемент каждого с. вектора сделаем > 0 *)
  ОТ i:=0 ДО посл ВЫП
    ЕСЛИ  СВ[i,0] < 0 ТО
      ОТ j:=0 ДО посл ВЫП
        СВ[i,j]:=-СВ[i,j]
      КОН 
    КОН 
  КОН;

  ВОЗВРАТ 0
КОН Якоби;

(******************************************************************************)
ЗАДАЧА Balance(A+:Матр.Вид);
(* Цель:  сбалансировать матрицу, т.е. уменьшить ее норму, не затрагивая
 *        с. значений
 ******************************************************************************
 * До:    < A > - исходная матрица
 * После: < A > - сбалансированная матрица *)
ПОСТ
  ОСН  = 2;  (* основание счисления машинных вычислений *)
  ОСН2 = ОСН*ОСН;
ПЕР
  i,j,посл:ЦЕЛ;
  c,f,g,r,s:Вещ;
  прошли:КЛЮЧ;
УКАЗ
  посл:=РАЗМЕР(A)-1;
  ПОВТОРЯТЬ
    прошли:=ВКЛ;
    ОТ i:=0 ДО посл ВЫП
      c:=0;
      r:=0;
      ОТ j:=0 ДО посл ВЫП
        ЕСЛИ  j # i ТО
          c:=c+МОДУЛЬ(A[j,i]);
          r:=r+МОДУЛЬ(A[i,j])
        КОН 
      КОН;
      (* проверка обнуления c и r, чтобы не было переполнения *)
      ЕСЛИ  (c # 0) И (r # 0) ТО
        g:=r/ОСН;
        f:=1;
        s:=c+r;
        ПОКА c < g ВЫП
          f:=f*ОСН;
          c:=c*ОСН2
        КОН;
        g:=r*ОСН;
        ПОКА c > g ВЫП
          f:=f/ОСН;
          c:=c/ОСН2
        КОН;
        (* теперь уравниваем *)
        ЕСЛИ  (c+r)/f < 0.95*s ТО
          прошли:=ОТКЛ;
          g:=1/f;
          ОТ j:=0 ДО посл ВЫП
            A[i,j]:=A[i,j]*g 
          КОН;
          ОТ j:=0 ДО посл ВЫП
            A[j,i]:=A[j,i]*f 
          КОН
        КОН
      КОН
    КОН
  ДО прошли
КОН Balance;

(******************************************************************************)
ЗАДАЧА ElmHes(A+:Матр.Вид);
(* исключение матрицы до верхней формы Гезенберга *)
ПЕР
  i,j,m,посл:ЦЕЛ;
  x,y:Вещ;
УКАЗ
  посл:=РАЗМЕР(A)-1;
  ОТ m:=1 ДО посл-1 ВЫП
    x:=0;
    i:=m;
    ОТ j:=m ДО посл ВЫП
      ЕСЛИ  МОДУЛЬ(A[j,m-1]) > МОДУЛЬ(x) ТО
        x:=A[j,m-1];
        i:=j
      КОН 
    КОН;
    ЕСЛИ  i # m ТО
      ОТ j:=m-1 ДО посл ВЫП
        Матем.обмен(A[i,j],A[m,j]) 
      КОН;
      ОТ j:=0 ДО посл ВЫП
        Матем.обмен(A[j,i],A[j,m]) 
      КОН
    КОН;
    ЕСЛИ  x # 0 ТО
      ОТ i:=m+1 ДО посл ВЫП
        y:=A[i,m-1];
        ЕСЛИ  y # 0 ТО
          y:=y/x;
          A[i,m-1]:=y;
          ОТ j:=m ДО посл ВЫП
            A[i,j]:=A[i,j]-y*A[m,j]
          КОН;
          ОТ j:=0 ДО посл ВЫП
            A[j,m]:=A[j,m]+y*A[j,i]
          КОН
        КОН
      КОН 
    КОН
  КОН;
  ОТ i:=2 ДО посл ВЫП
    ОТ j:=0 ДО i-2 ВЫП
      A[i,j]:=0 
    КОН 
  КОН
КОН ElmHes;

(******************************************************************************)
ЗАДАЧА Hqr(A+:Матр.Вид; сзВещ+,сзМнм+:Вект.Вид):ЦЕЛ;
(* находит с. значения у верхней матрицы Гезенберга *)
ПЕР
  i,Its,j,k,l,m,n,посл:ЦЕЛ;
  Anorm,p,q,r,s,t,u,v,w,x,y,z:Вещ;

  ЗАДАЧА Sign(a,b:Вещ):Вещ;
  УКАЗ
    ЕСЛИ  b < 0 ТО ВОЗВРАТ -МОДУЛЬ(a) ИНАЧЕ ВОЗВРАТ МОДУЛЬ(a) КОН
  КОН Sign;

УКАЗ
  посл:=РАЗМЕР(A)-1;
  (* вычисление нормы *)
  k:=0;
  Anorm:=0;
  ОТ i:=0 ДО посл ВЫП
    ОТ j:=k ДО посл ВЫП
      Anorm:=Anorm+МОДУЛЬ(A[i,j]) 
    КОН;
    k:=i 
  КОН;
  n:=посл;
  t:=0;
  Its:=0;
  КОЛЬЦО
(* 60: *)
(* 70: *)
    (* поиск малого одиночного поддиагонального элемента *)
    l:=n;
    КОЛЬЦО
      ЕСЛИ  l < 1 ТО
        ВЫХОД
      КОН;
        s:=МОДУЛЬ(A[l-1,l-1])+МОДУЛЬ(A[l,l]);
      ЕСЛИ  s = 0 ТО
        s:=Anorm
      КОН;
      ЕСЛИ  s+МОДУЛЬ(A[l,l-1]) = s ТО 
        ВЫХОД
      КОН;
      УМЕНЬШИТЬ(l)
    КОН;
(* 100: *)
    ЕСЛИ  l = n ТО
(* 270: *)
      (* нашли однократный корень *)
      сзВещ[n]:=A[n,n]+t;
      сзМнм[n]:=0;
      n:=n-1;
      ЕСЛИ  n < 0 ТО
        ВОЗВРАТ 0
      КОН;
      Its:=0
      (* goto 60 *)
    ИНАЧЕ
      (* формируем сдвиг *)
      x:=A[n,n];
      y:=A[n-1,n-1];
      w:=A[n,n-1]*A[n-1,n];
      ЕСЛИ  l = n-1 ТО
(* 280: *)
        (* нашли кратный корень *)
        p:=0.5*(y-x);
        q:=Матем.кв(p)+w;
        z:=Матем.квкор(МОДУЛЬ(q));
        x:=x+t;
        ЕСЛИ  q >= 0 ТО
          (* действительноя пара *)
          z:=p+Sign(z,p);
          сзВещ[n]:=x+z;
          сзВещ[n-1]:=сзВещ[n];
          ЕСЛИ  z # 0 ТО сзВещ[n]:=x-w/z КОН;
          сзМнм[n]:=0;
          сзМнм[n-1]:=0
        ИНАЧЕ
(* 320: *)
          (* комплексная пара *)
          сзВещ[n]:=x+p;
          сзВещ[n-1]:=сзВещ[n];
          сзМнм[n]:=-z;
          сзМнм[n-1]:=z
        КОН;
(* 330: *)
        n:=n-2;
        ЕСЛИ  n < 0 ТО
          ВОЗВРАТ 0
        КОН;
        Its:=0
        (* goto 60 *)
      ИНАЧЕ
        УВЕЛИЧИТЬ(Its);
        ЕСЛИ  (Its = 10) ИЛИ (Its = 20) ТО
          (* формируем исключительный сдвиг *)
          t:=t+x;
          ОТ i:=0 ДО n ВЫП
            A[i,i]:=A[i,i]-x 
          КОН;
          s:=МОДУЛЬ(A[n,n-1])+МОДУЛЬ(A[n-1,n-2]);
          x:=0.75*s;
          y:=x;
          w:=-0.4375*Матем.кв(s)
        АЕСЛИ  Its = 30 ТО
          ВОЗВРАТ Матр.НЕТ_СХОДИМОСТИ
        КОН;
(* 130: *)
        (* поиск двух малых смежных поддиагональных элементов *)
        m:=n-2;
        КОЛЬЦО
          ЕСЛИ  m < l ТО
            ВЫХОД
          КОН;
          z:=A[m,m];
          r:=x-z;
          s:=y-z;
          p:=(r*s-w)/A[m+1,m]+A[m,m+1];
          q:=A[m+1,m+1]-z-r-s;
          r:=A[m+2,m+1];
          s:=МОДУЛЬ(p)+МОДУЛЬ(q)+МОДУЛЬ(r);
          p:=p/s;
          q:=q/s;
          r:=r/s;
          ЕСЛИ  m = l ТО 
            ВЫХОД
          КОН;
          v:=МОДУЛЬ(p)*(МОДУЛЬ(A[m-1,m-1])+МОДУЛЬ(z)+МОДУЛЬ(A[m+1,m+1]));
          u:=МОДУЛЬ(A[m,m-1])*(МОДУЛЬ(q)+МОДУЛЬ(r));
          ЕСЛИ  u+v=v ТО 
            ВЫХОД
          КОН;
          УМЕНЬШИТЬ(m)
        КОН;
(* 150: *)
        ОТ i:=m+2 ДО n ВЫП
          A[i,i-2]:=0;
          ЕСЛИ  i # (m+2) ТО 
            A[i,i-3]:=0
          КОН 
        КОН;
        (* двойной QR шаг разрешая строки l на n и столбцы m на n *) 
        ОТ k:=m ДО n-1 ВЫП
          ЕСЛИ  k # m ТО
            p:=A[k,k-1];
            q:=A[k+1,k-1];
            r:=0;
            ЕСЛИ  k # (n-1) ТО
              r:=A[k+2,k-1]
            КОН;
            x:=МОДУЛЬ(p)+МОДУЛЬ(q)+МОДУЛЬ(r);
            ЕСЛИ  x # 0 ТО
              p:=p/x;
              q:=q/x;
              r:=r/x
            КОН 
          КОН;
(* 170: *)
          s:=Sign(Матем.квкор(Матем.кв(p)+Матем.кв(q)+Матем.кв(r)),p);
          ЕСЛИ  s # 0 ТО
            ЕСЛИ  k = m ТО
              ЕСЛИ  l # m ТО
                A[k,k-1]:=-A[k,k-1]
              КОН
            ИНАЧЕ
              A[k,k-1]:=-s*x
            КОН;
            p:=p+s;
            x:=p/s;
            y:=q/s;
            z:=r/s;
            q:=q/p;
            r:=r/p;
            (* изменение строк *)
            ОТ j:=k ДО n ВЫП
              p:=A[k,j]+q*A[k+1,j];
              ЕСЛИ  k # (n-1) ТО
                p:=p+r*A[k+2,j];
                A[k+2,j]:=A[k+2,j]-p*z
              КОН;
              A[k+1,j]:=A[k+1,j]-p*y;
              A[k,j]:=A[k,j]-p*x
            КОН;
            (* изменение столбцов *)
            ОТ i:=l ДО Матем.минЦ(n,k+3) ВЫП
              p:=x*A[i,k]+y*A[i,k+1];
              ЕСЛИ  k # (n-1) ТО
                p:=p+z*A[i,k+2];
                A[i,k+2]:=A[i,k+2]-p*r
              КОН;
              A[i,k+1]:=A[i,k+1]-p*q;
              A[i,k]:=A[i,k]-p
            КОН 
          КОН 
        КОН
      КОН 
    КОН 
  КОН
КОН Hqr;

(******************************************************************************)
ЗАДАЧА Значения-(A+:Матр.Вид; сзВещ+,сзМнм+:Вект.Вид):ЦЕЛ;
(* Цель:  вычисление с. значений квадратной матрицы
 ******************************************************************************
 * До:    < A >   - исходная матрица
 * После: <сзВещ> - вещественная часть с. значений
 *        <сзМнм> - мнимая часть с. значений
 *        < A >   - разрушенная исходная матрица
 * Ответ: 0 или НЕТ_СХОДИМОСТИ *)
УКАЗ
  Balance(A);
  ElmHes(A);
  ВОЗВРАТ Hqr(A,сзВещ,сзМнм)
КОН Значения;

(******************************************************************************)
ЗАДАЧА Вектор-(A-:Матр.Вид; сз,точность:Вещ; св+:Вект.Вид):ЦЕЛ;
(* Цель:  вычисление одного с. вектора для соответствующего
 *        вещественного (кратного) с. значения
 ******************************************************************************
 * До:    < A >    - исходная матрица
 *        < сз >   - с. значение
 *        <точность> - требуемая точность
 * После: < св >     - нормированный с. вектор, 
 *                   у которого первый элемент > 0
 * Ответ: 0 или НЕТ_СХОДИМОСТИ *)
ПЕР
  код,i,посл:ЦЕЛ;
  A1:Матр.Доступ;

  ЗАДАЧА SetMatrix(A-,A1+:Матр.Вид; сз:Вещ);
  (* строит A1 = A-сз*i *)
  ПЕР
    i:ЦЕЛ;
  УКАЗ
    Матр.Списать(A,A1);
    ОТ i:=0 ДО РАЗМЕР(A)-1 ВЫП
      A1[i,i]:=A[i,i]-сз 
    КОН
  КОН SetMatrix;

  ЗАДАЧА Solve(A-:Матр.Вид; n:ЦЕЛ; точность:Вещ; св+:Вект.Вид):ЦЕЛ;
  (* решает систему A*x = 0 после закрепления за n-м неизвестным 1 *)
  ПЕР
    A1,W:Матр.Доступ;
    b,s,x:Вект.Доступ;
    код,i,i1,j,j1,посл:ЦЕЛ;
  УКАЗ
    посл:=РАЗМЕР(A)-1;
    СОЗДАТЬ(A1,посл,посл);
    СОЗДАТЬ(W,посл,посл);
    СОЗДАТЬ(b,посл);
    СОЗДАТЬ(s,посл);
    СОЗДАТЬ(x,посл);

    i1:=0;
    ОТ i:=0 ДО посл ВЫП
      ЕСЛИ  i # n ТО
        j1:=0;
        ОТ j:=0 ДО посл ВЫП
          ЕСЛИ  j # n ТО
            A1[i1,j1]:=A[i,j];
            УВЕЛИЧИТЬ(j1)
          КОН
        КОН;
        b[i1]:=-A[i,n];
        УВЕЛИЧИТЬ(i1)
      КОН 
    КОН;

    код:=Матр.РазложитьНаSV(A1^,s^,W^);

    ЕСЛИ  код = 0 ТО
      Матр.ОбнулитьS(s^,точность);
      Матр.РешитьИзSV(A1^,s^,W^,b^,x^);

      (* обновить с. вектор *)
      i1:=0;
      ОТ i:=0 ДО посл ВЫП
        ЕСЛИ  i = n ТО
          св[i]:=1
        ИНАЧЕ
          св[i]:=x[i1];
          УВЕЛИЧИТЬ(i1)
        КОН 
      КОН
    КОН;
    ВОЗВРАТ код;
  КОН Solve;

  ЗАДАЧА ZeroVector(b-:Вект.Вид; точность:Вещ):КЛЮЧ;
  (* ВКЛ, если вектор b 0-й *)
  ПЕР
    i:ЦЕЛ;
  УКАЗ
    ОТ i:=0 ДО РАЗМЕР(b)-1 ВЫП
      ЕСЛИ  МОДУЛЬ(b[i]) >= точность ТО
        ВОЗВРАТ ОТКЛ
      КОН
    КОН;
    ВОЗВРАТ ВКЛ
  КОН ZeroVector;

  ЗАДАЧА CheckEigenVector(A1-:Матр.Вид; св-:Вект.Вид; точность:Вещ):КЛЮЧ;
  (* ВКЛ, если выполняется равенство A1*св = 0 *)
  ПЕР
    i,k,посл:ЦЕЛ;
    b:Вект.Доступ;
  УКАЗ
    посл:=РАЗМЕР(A1)-1;
    СОЗДАТЬ(b,посл+1);
    (* строим b = A1*св *)
    ОТ i:=0 ДО посл ВЫП
      ОТ k:=0 ДО посл ВЫП
        b[i]:=b[i]+A1[i,k]*св[k]
      КОН 
    КОН;
    ВОЗВРАТ ZeroVector(b^,точность)
  КОН CheckEigenVector;

  ЗАДАЧА Normalize(св+:Вект.Вид);
  (* нормируем с. вектор и устанавливаем первый элемент >= 0 *)
  ПЕР
    сумма,Norm:Вещ;
    i,посл:ЦЕЛ;
  УКАЗ
    посл:=РАЗМЕР(св)-1;
    сумма:=0;
    ОТ i:=0 ДО посл ВЫП
      сумма:=сумма+Матем.кв(св[i]) 
    КОН;
    Norm:=Матем.квкор(сумма);
    ОТ i:=0 ДО посл ВЫП
      св[i]:=св[i]/Norm 
    КОН;
    ЕСЛИ  св[0] < 0 ТО
      ОТ i:=0 ДО посл ВЫП
        св[i]:=-св[i]
      КОН 
    КОН
  КОН Normalize;

УКАЗ
  посл:=РАЗМЕР(A)-1;
  СОЗДАТЬ(A1,посл+1,посл+1);

  (* строим A1 = A-сз*i *)
  SetMatrix(A,A1^,сз);

  (* попытаться решить систему A1*св=0 исключая 1 уравнение *)
  ОТ i:=0 ДО посл ВЫП
    ЕСЛИ  (Solve(A1^,i,точность,св) = 0) И CheckEigenVector(A1^,св,точность) ТО
      Normalize(св);
      ВОЗВРАТ 0
    КОН
  КОН;
  ВОЗВРАТ Матр.НЕТ_СХОДИМОСТИ 
КОН Вектор;

(******************************************************************************)
ЗАДАЧА КорниПолинома-(Coef-:Вект.Вид; Deg:ЦЕЛ; X_Re+,X_Im+:Вект.Вид):ЦЕЛ;
(* Цель:  вычисление действительных и комплексных корней действительного
 *        полинома методом companion матрицы
 ******************************************************************************
 * До:    < Coef > - коэффициенты полинома
 *        < Deg >  - степень полинома
 * После: < X_Re > - действительные части корней (в порядке возрастания)
 *        < X_Im > - мнимые части корней
 * Ответ: 0 или НЕТ_СХОДИМОСТИ *)
ПЕР
  A:Матр.Доступ;   (* companion матрица *)
  n:ЦЕЛ;           (* размер матрицы  *)
  i,j,k:ЦЕЛ;  
  код:ЦЕЛ;
  врем:Вещ;
УКАЗ
  n:=Deg-1;
  СОЗДАТЬ(A,n+1,n+1);

  (* заполняем companion матрицу *)
  ОТ j:=0 ДО n ВЫП
    A[0,j]:=-Coef[Deg-j-2]/Coef[Deg-1]
  КОН;
  ОТ j:=0 ДО n-1 ВЫП
    A[j+1,j]:=1 
  КОН;

  (* корни полинома являются и с. значениями companion матрицы *)
  Balance(A^);
  код:=Hqr(A^,X_Re,X_Im);

  ЕСЛИ  код = 0 ТО
    (* упорядочивание корней в порядке возрастания действительных частей *)
    ОТ i:=0 ДО n-1 ВЫП
      k:=i;
      врем:=X_Re[i];
      ОТ j:=i+1 ДО n ВЫП
        ЕСЛИ  X_Re[j] < врем ТО
          k:=j;
          врем:=X_Re[j]
        КОН 
      КОН;
      Матем.обмен(X_Re[i],X_Re[k]);
      Матем.обмен(X_Im[i],X_Im[k])
    КОН
  КОН;
  ВОЗВРАТ код
КОН КорниПолинома;

КОН Собств.

 
 


Вопросы, замечания и предложения высылайте на atimopheyev@yahoo.com

 
Главная     ◄Глагол     ◄Азбука     ◄Задачи на Глаголе     Примеры приложений ►   Среда разработки ►   Отладка программ ►   Отличия от Оберона ►   Отличия от Паскаля ►   Ассемблер ARM ►   Глагол для ARM ►   ? и Ответы